home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 1
/
Cream of the Crop 1.iso
/
PROGRAM
/
PCW_C.ARJ
/
REORDER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-18
|
19KB
|
440 lines
/***********************************************************/
/* File Id. Reorder.C. */
/* Author. Stan Milam. */
/* Date Written. 02/06/89. */
/* */
/* (c) Copyright 1989, 1990 by Stan Milam */
/* */
/* Comments: The functions in this file control & maintain*/
/* a list of all windows being used. When a window is */
/* pushed it is added to the list and occupies the first */
/* position in the list. When a window is poped it is re- */
/* moved from the list, hidden and deleted. If a window in*/
/* the middle or end of the list is addressed that window */
/* is floated to the top of the list recursively. The */
/* variable, topwnd, always points to the beginning of the */
/* list. */
/***********************************************************/
#if __TURBOC__ || __ZTC__
# define _fmalloc farmalloc
# define _ffree farfree
# if __TURBOC__
# include <alloc.h>
# endif
#else
# include <malloc.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "pcw.i"
#include "pcwproto.h"
#define USER 1 /* User hidden attribute */
#define SYSTEM 2 /* System hidden attribute */
/* Function Prototypes of local functions */
static int chk_wnds(WNDPTR *wnd);
static int hide_wnd(WNDPTR *wnd, int attribute);
static int show_wnd(WNDPTR *wnd, int attribute);
static int wnd_overlap(WNDPTR *wnd1, WNDPTR *wnd2);
static void level_wnds(WNDPTR *wnd);
static void remove_from_list(WNDPTR *wnd);
static void reshow_wnds(WNDPTR *wnd);
static void insert_first_in_list(WNDPTR *wnd);
static void change_wnd_position(WNDPTR *wnd,int row,int col,int cl,int rw);
static WNDPTR *topwnd = (WNDPTR *) NULL;
/************************************************************/
/* Get_Active_Wnd */
/* */
/* Returns the most active (top) window. If no windows are */
/* up returns NULL. */
/************************************************************/
WNDPTR *get_active_wnd(void) {
return(topwnd);
}
/************************************************************/
/* Wndmove */
/* */
/* This function will handle moving a window from one place */
/* on the screen to another. It is placed in this file */
/* because it needs close proximity to the hide/show func- */
/* tions. */
/************************************************************/
int wndmove(WNDPTR *wnd, int row, int col) {
int rw, cl;
if (!chk_video_state(&rw,&cl)) return(0);
if (wnd->hideflag == USER) { /* If hidden then */
change_wnd_position(wnd,row,col,cl,rw); /* Change position */
return(1); /* And return */
}
if (chk_wnds(wnd)) { /* Remove overlapping winds */
hide_wnd(wnd, SYSTEM); /* Hide our wnd */
reshow_wnds(wnd->back); /* Show overlaps */
change_wnd_position(wnd,row,col,cl,rw); /* Change our position */
show_wnd(wnd, SYSTEM); /* And Show it */
}
else {
hide_wnd(wnd, SYSTEM); /* No overlaps so hide */
change_wnd_position(wnd,row,col,cl,rw); /* Change position */
show_wnd(wnd, SYSTEM); /* And show it */
}
remove_from_list(wnd); /* Move wnd to first */
insert_first_in_list(wnd); /* In list */
level_wnds(topwnd); /* Relevel all windows */
return(1); /* Return */
}
/***********************************************************/
/* Change_Wnd_Position */
/* */
/* This function calculates the new position of a window. */
/* Checks that it will be in bounds of screen and adjusts */
/* if it is not. */
/***********************************************************/
static void change_wnd_position(WNDPTR *wnd,int row,int col,int cl,int rw) {
int rows, cols;
rows = (wnd->lrow - wnd->urow); /* Calc total rows */
cols = (wnd->lcol - wnd->ucol); /* Same for cols */
if (row < 1) row = 1;
if (col < 1) col = 1;
if ((col + cols) > cl) { /* Is it in bounds */
cl = (col + cols) - cl;
col = col - cl;
}
if ((row + rows) > rw) { /* Is it in bounds? */
rw = (row + rows) - rw; /* No - Adjust the rows */
row= row - rw;
}
wnd->urow = row; /* Save in wnd structure */
wnd->ucol = col;
wnd->lrow = row + rows;
wnd->lcol = col + cols;
}
/************************************************************/
/* Re_Order */
/* */
/* This function is the main driver for the window list */
/* management routines. Its job, depending on the action to*/
/* be taken is to handle the logic of managing how the */
/* windows are ordered visibly, and how they are ordered */
/* logically in the window list. */
/************************************************************/
void re_order(WNDPTR *wnd, int action) {
switch(action) {
case NORMAL : /* Bring window to surface */
if (wnd->level == 1) return; /* If first in list-forget it */
if (chk_wnds(wnd)) { /* If window overlap then */
hide_wnd(wnd, SYSTEM); /* Hide our window */
reshow_wnds(wnd->back); /* Show those that were hid */
show_wnd(wnd, SYSTEM); /* Put ours on top */
}
remove_from_list(wnd); /* Remove from window list */
insert_first_in_list(wnd); /* Make it the logical first */
break;
case PUSH : /* Adding a new window to list */
insert_first_in_list(wnd); /* Insert it first */
break; /* Over & Out! */
case POP : /* For pops */
if (wnd->hideflag) { /* If window hidden */
remove_from_list(wnd); /* Remove it from list */
break; /* And get out */
}
if (wnd->level == 1) { /* If first in list */
remove_from_list(wnd); /* Remove it */
hide_wnd(wnd, SYSTEM); /* Hide it */
}
else {
if (chk_wnds(wnd)) { /* If someone overlaps */
hide_wnd(wnd, SYSTEM); /* Hide ours */
reshow_wnds(wnd->back); /* Reshow other windows */
}
else hide_wnd(wnd, SYSTEM); /* No overlaps - so hide */
remove_from_list(wnd); /* Remove from list */
}
break;
case HIDE :
if (wnd->level == 1) { /* If first window... */
hide_wnd(wnd, USER); /* Hide it with user attribute */
return; /* and return */
}
if (chk_wnds(wnd)) { /* Remove overlaps if any */
hide_wnd(wnd, USER); /* Hide window with user attr */
reshow_wnds(wnd->back); /* Reshow the overlaps */
}
else {
hide_wnd(wnd, USER); /* No overlaps so just hide */
return; /* Return */
}
break;
case SHOW :
if (wnd->hideflag != USER) /* Do not try to show a */
return; /* Window not hidden */
show_wnd(wnd, USER); /* Show the window */
remove_from_list(wnd); /* Put the window first in */
insert_first_in_list(wnd); /* List */
break;
}
level_wnds(topwnd); /* Relevel the windows. */
}
/************************************************************/
/* Remove_From_List */
/* */
/* This routine will remove a window from the window list. */
/* The logic is most likely more complicated than needed but*/
/* better safe than sorry when worrying about null pointer */
/* assignments. */
/************************************************************/
static void remove_from_list(WNDPTR *wnd) {
if (wnd->back == NULL) { /* Means its the top */
if (wnd->next == NULL) /* Means its the only one */
topwnd = (WNDPTR *) NULL; /* Set the top to NULL */
else {
wnd->next->back = (WNDPTR *) NULL; /* Set the back to NULL */
topwnd = wnd->next; /* Make the next on top */
}
}
else { /* Its in middle or at end */
if (wnd->next == NULL) /* Its the end */
wnd->back->next = (WNDPTR *) NULL; /* Cut it out of list */
else { /* Its in the middle */
wnd->next->back = wnd->back; /* Remove & reset all */
wnd->back->next = wnd->next; /* the pointers */
}
}
}
/************************************************************/
/* Insert_First_In_List */
/* */
/* The name says it all. A little logic to protect against */
/* the dreaded "Null Pointer Assignment" message. */
/************************************************************/
static void insert_first_in_list(WNDPTR *wnd) {
wnd->next = (WNDPTR *) topwnd; /* Insert it first in list */
wnd->back = (WNDPTR *) NULL; /* Back always set to NULL */
if (topwnd != NULL) /* If topwnd = NULL then */
topwnd->back = wnd; /* NO assignment PLEASE */
topwnd = wnd; /* Make our wnd first */
}
/*************************************************************/
/* Chk_Wnds */
/* */
/* This routine recursively determines if a window is over- */
/* lapping another. If a window is found to be overlapping */
/* it must hide that window, but first it must determine if */
/* a window above it is overlapping so it calls itself. */
/* It will work its way down - and up - the list removing */
/* all overlapping windows. */
/*************************************************************/
static int chk_wnds(WNDPTR *wnd) {
WNDPTR *wrkwnd;
int overlap;
wrkwnd = topwnd; /* Start with top window */
overlap= 0; /* Set local auto to false */
while (wrkwnd->level < wnd->level) { /* While 1 less than level */
if (!wrkwnd->hideflag) { /* If its hidden forget it */
if (wnd_overlap(wrkwnd, wnd)) { /* If they overlap */
overlap = 1; /* Set our switch */
chk_wnds(wrkwnd); /* Recurse with new window */
hide_wnd(wrkwnd, SYSTEM); /* Finally hide it */
}
}
wrkwnd = wrkwnd->next; /* Grab next window */
}
return (overlap); /* Return our switch setting */
}
/************************************************************/
/* Reshow_Wnds */
/* */
/* This function reshows any windows we had to hide along */
/* the way. It runs thru the list backwards to the beginning*/
/************************************************************/
static void reshow_wnds(WNDPTR *wnd) {
while (wnd) { /* Run Backwards thru the */
if (wnd->hideflag != USER) /* If user attr skip */
show_wnd(wnd, SYSTEM); /* List showing windows */
wnd = wnd->back; /* We pulled off */
}
}
/* */
/************************************************************/
/* Level_Wnds */
/* */
/* This funtion runs thru the list from the beginning and */
/* reassignes level values to each window after and inser- */
/* tion or deletion. */
/************************************************************/
static void level_wnds(WNDPTR *wnd) {
int i = 1;
WNDPTR *wrkwnd;
wrkwnd = wnd;
while (wrkwnd) { /* While window pointer not NULL */
wrkwnd->level = i++; /* Assign a new level number */
wrkwnd = wrkwnd->next; /* Get next window */
}
}
/************************************************************/
/* Hide_Wnd */
/* */
/* This routine will hide a specified window with one of two*/
/* attributes, USER & SYSTEM. The system attribute means */
/* the window system is hiding the window for its own */
/* purposes and is a temporary hide while the user attribute*/
/* means the user wanted to hide the window and leave it */
/* hidden until it is desired to be shown. USER overrides */
/* SYSTEM, meaning if the system is running thru the list */
/* showing all SYSTEM hidden windows the USER hidden will */
/* be ignored. */
/************************************************************/
static int hide_wnd(WNDPTR *wnd, int attribute) {
int rows, cols, page, pagesize;
unsigned offset, scrnseg;
int far *scrnptr;
if (wnd->hideflag) return(1); /* Can't hide again */
if (wnd->wbuffer == (char far *) NULL)
return(0);
cols = (wnd->lcol - wnd->ucol) + 1; /* Calc total cols */
rows = (wnd->lrow - wnd->urow) + 1; /* And rows */
page = wnd->page;
if (wnd->wsave == (char far *) NULL) {
wnd->wsave = (char far *) _fmalloc((rows * cols) * 2);
if (wnd->wsave == (char far *) NULL)
return(0);
}
pagesize = getpagesize();
scrnseg = getscrnseg();
offset = MK_SCRNOFF(wnd->urow,wnd->ucol);
scrnptr = (int far *) MK_FP(scrnseg, offset);
SaveScrn(rows, cols, scrnptr, wnd->wsave);
RestoreScrn(rows, cols, scrnptr, wnd->wbuffer);
wnd->hideflag = attribute;
return(1);
}
/************************************************************/
/* Show_Wnd */
/* */
/* This function will show the windows that were hidden. */
/* If the show is with attribute SYSTEM and the window was */
/* hidden with USER we will bypass. */
/************************************************************/
static int show_wnd(WNDPTR *wnd, int attribute) {
int rows, cols, page, pagesize;
unsigned scrnseg, offset;
int far *scrnptr;
if (wnd->wbuffer == NULL || wnd->wsave == NULL) /* Exit if not */
return(0); /* Ever allocated */
if (wnd->hideflag != attribute) /* Can't show if */
return(0); /* Attr don't match */
wnd->hideflag = 0; /* Reset hideflag */
rows = (wnd->lrow - wnd->urow) + 1; /* Calc total rows */
cols = (wnd->lcol - wnd->ucol) + 1; /* And Cols */
page = wnd->page; /* Get the scrn page */
scrnseg = getscrnseg(); /* Get scrn segment */
pagesize= getpagesize(); /* get pagesize */
offset = MK_SCRNOFF(wnd->urow,wnd->ucol); /* Calc offset */
scrnptr = (int far *) MK_FP(scrnseg, offset); /* Make a far pointer */
SaveScrn(rows, cols, scrnptr, wnd->wbuffer); /* Save whats there */
RestoreScrn(rows, cols, scrnptr, wnd->wsave); /* Put the wnd down */
return(1); /* Return */
}
/************************************************************/
/* Wnd_Overlap */
/* */
/* This routine determines if two windows overlap the same */
/* portion of the screen. It is a bit difficult to tell how*/
/* it works. I had to draw myself some pictures of over- */
/* lapping windows to figure it out. */
/************************************************************/
static int wnd_overlap(WNDPTR *wnd1, WNDPTR *wnd2) {
if (wnd1->page != wnd2->page) /* If not in same page */
return(0); /* they can't overlap */
if (((wnd2->ucol >= wnd1->ucol) && (wnd2->ucol <= wnd1->lcol)) &&
(((wnd2->urow >= wnd1->urow) && (wnd2->urow <= wnd1->lrow)) ||
((wnd2->lrow >= wnd1->urow) && (wnd2->lrow <= wnd1->lrow))))
return(1);
if (((wnd2->lcol >= wnd1->ucol) && (wnd2->lcol <= wnd1->lcol)) &&
(((wnd2->urow >= wnd1->urow) && (wnd2->urow <= wnd1->lrow)) ||
((wnd2->lrow >= wnd1->urow) && (wnd2->lrow <= wnd1->lrow))))
return(1);
if (((wnd1->ucol >= wnd2->ucol) && (wnd1->lcol <= wnd2->lcol)) &&
(((wnd1->urow >= wnd2->urow) && (wnd1->urow <= wnd2->lrow)) ||
((wnd1->lrow >= wnd2->urow) && (wnd1->lrow <= wnd2->lrow))))
return(1);
if (((wnd1->urow >= wnd2->urow) && (wnd1->lrow <= wnd2->lrow)) &&
(((wnd1->ucol >= wnd2->ucol) && (wnd1->ucol <= wnd2->lcol)) ||
((wnd1->lcol >= wnd2->ucol) && (wnd1->lcol <= wnd2->lcol))))
return(1);
if ((wnd1->ucol > wnd2->ucol && wnd1->lcol < wnd2->lcol) &&
(wnd1->urow > wnd2->urow && wnd1->lrow < wnd2->lrow))
return(1);
return(0);
}